﻿Public Class NumberBox
	Inherits TextBox

	Dim DecimalSymbol As String
	Dim GroupSymbol As String
	Dim m_DecimalDigits As Integer

	Public Overrides Property Value() As Object
		Get
			If Text = "" Then Return DBNull.Value
			Return CDec(Replace(Text, GroupSymbol, ""))
		End Get
		Set(ByVal Value As Object)
			If IsDBNull(Value) Then
				Text = ""
				Exit Property
			End If
			If Not IsNumeric(Value) Then
				Text = ""
				Exit Property
			End If
			Text = Format(CDec(Value), FormatString)
		End Set
	End Property

	Property DecimalDigits() As Integer
		Get
			Return m_DecimalDigits
		End Get
		Set(ByVal Value As Integer)
			m_DecimalDigits = Value
		End Set
	End Property

	Private Sub NumberBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.TextChanged
		RaiseChangeEvent()
	End Sub

	Private Sub NumberBox_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
		If [ReadOnly] Then Exit Sub
		If (e.Shift And e.KeyCode = Keys.Delete) Or (e.Control And e.KeyCode = Keys.X) Then
			e.Handled = True
			Clipboard.SetText(SelectedText, TextDataFormat.Text)
			ProcessNumberKey("delete")
		End If
		If Not (e.Shift Or e.Control) And e.KeyCode = Keys.Delete Then
			e.Handled = True
			ProcessNumberKey("delete")
		End If
		If (e.Shift And e.KeyCode = Keys.Insert) Or (e.Control And e.KeyCode = Keys.V) Then
			e.Handled = True
			ProcessNumberKey("insert")
		End If
	End Sub

	Private Sub NumberBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress
		If [ReadOnly] Then Exit Sub
		Dim Key = e.KeyChar
		e.Handled = True
		If SelectionLength > 0 Then
			ProcessNumberKey("delete")
		End If
		ProcessNumberKey(Key)
	End Sub

	Sub ProcessNumberKey(ByVal Key)
		Dim Ins = ""
		Dim Pos As Integer
		Dim Data As String
		Dim OldLength
		Dim i
		Data = Text
		OldLength = Len(Data)
		Select Case Key
			Case "insert"
				Ins = Clipboard.GetText(1)
				For i = 0 To 255
					If InStr("0123456789" & DecimalSymbol, Chr(i)) = 0 Then Ins = Replace(Ins, Chr(i), "")
				Next i
			Case "delete"
				If Text = SelectedText Then
					Text = ""
					Exit Sub
				End If
				Select Case SelectedText
					Case DecimalSymbol, GroupSymbol : Exit Sub
				End Select
				If SelectionLength = 0 Then SelectionLength = 1
				Select Case SelectedText
					Case DecimalSymbol, GroupSymbol
						SelectionStart = SelectionStart + 1
						SelectionLength = 1
				End Select
			Case Chr(8)	'Backspace
				If SelectionLength > 0 Then
					ProcessNumberKey("delete")
					Exit Sub
				End If
				Select Case SelectedText
					Case DecimalSymbol, GroupSymbol : Exit Sub
				End Select
				If SelectionStart = 0 Then Exit Sub
				If Mid(Text, SelectionStart, 1) = DecimalSymbol Then
					SelectionStart = SelectionStart - 1
					Exit Sub
				End If
				SelectionStart -= 1
				SelectionLength = 1
			Case "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
				'If Key = "0" And SelectionStart = 0 Then Exit Sub
				Ins = Key
			Case ".", ","
				If m_DecimalDigits > 0 Then
					SelectionStart = Len(Text) - m_DecimalDigits
					Exit Sub
				End If
			Case Else
				Exit Sub
		End Select
		Pos = Len(Text) - SelectionStart - SelectionLength
		Data = Strings.Left(Data, SelectionStart) & Ins & Mid(Data, SelectionStart + SelectionLength + 1)
		Data = Replace(Data, GroupSymbol, "")
		If m_DecimalDigits > 0 Then
			If Data = Ins Then Pos = m_DecimalDigits + 1
			If Data = "" Then Data = "0" : Pos = 10
			If Data = "." Then Data = "0" : Pos = m_DecimalDigits - 1
			Do Until InStr(Data, DecimalSymbol) = InStrRev(Data, DecimalSymbol)
				Data = Strings.Left(Data, InStrRev(Data, DecimalSymbol) - 1)
			Loop
			Data = Format(CDec(Data), FormatString)
		ElseIf Data <> "" Then
			If Not IsNumeric(Data) Then Exit Sub
			Data = Format(CDec(Data), FormatString)
		End If
		Text = Data
		Pos = Len(Text) - Pos
		If Len(Data) = OldLength Then Pos += If(Key = Chr(8) Or Key = "delete", -1, 1)
		If Pos < 0 Then Pos = 0
		SelectionStart = Pos
		SelectionLength = 0
	End Sub

	Function FormatString() As String
		Return "###,###,###,###,##" & If(m_DecimalDigits = 0, "0", "#." & Strings.StrDup(m_DecimalDigits, "0"))
	End Function

	Public Sub New()
		DecimalSymbol = Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator
		DecimalSymbol = Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator
		GroupSymbol = Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyGroupSeparator
		GroupSymbol = Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberGroupSeparator
		TextAlign = HorizontalAlignment.Right
	End Sub

	Public Overrides ReadOnly Property IsEmpty() As Boolean
		Get
			Return IsDBNull(Value)
		End Get
	End Property

	Public Overrides Function Errors() As String
		If IsRequired AndAlso IsEmpty Then Return Caption & " alanı boş olamaz."
		Return ""
	End Function

End Class